package com.meis.widget.xiaohongshu;

import com.ryan.ohos.extension.ViewConfiguration;
import ohos.agp.animation.Animator;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.ScrollHelper;
import ohos.agp.render.Canvas;
import ohos.agp.utils.Rect;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;

import org.jetbrains.annotations.Nullable;

/**
 * Created by wenshi on 2019/3/6.
 * Description
 */
public class CoordinatorLinearLayout extends DirectionalLayout {
    // 是否展开
    private boolean mIsExpand = true;
    private int initHeight = 0;
    private int initTop = 0;
    private boolean isInit = false;
    private ScrollHelper mOverScroller;

    // 快速抛的最小速度
    private int mMinFlingVelocity;

    // 滚动最大距离 = 图片裁剪控件的高度
    private int mScrollRange;

    // 滚动监听接口
    private OnScrollListener mListener;

    // 最大展开因子
    private static final int MAX_EXPAND_FACTOR = 6;
    // 滚动时长
    private static final int SCROLL_DURATION = 500;
    private AnimatorValue animatorValue = new AnimatorValue();

    public CoordinatorLinearLayout(Context context) {
        this(context, null);
    }

    public CoordinatorLinearLayout(Context context, @Nullable AttrSet attrs) {
        this(context, attrs, "");
    }

    public CoordinatorLinearLayout(Context context, @Nullable AttrSet attrs, String defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mOverScroller = new ScrollHelper();
        mMinFlingVelocity = ViewConfiguration.getMinimumFlingVelocity();
        // 设置默认值 =  图片裁剪控件的宽度
        mScrollRange = DisplayManager.getInstance().getDefaultDisplay(context)
                .orElse(null).getRealAttributes().width;

        getComponentTreeObserver().addScrolledListener(this::computeScroll);
        setScrollbarOverlapEnabled(true);
        addDrawTask(new DrawTask() {
            @Override
            public void onDraw(Component component, Canvas canvas) {
                if (!isInit) {
                    initHeight = getBottom();
                    initTop = getTop();
                    isInit = true;
                }
            }
        });
    }

    public int getInitHeight() {
        return initHeight;
    }

    /**
     * 触摸点是否view的区域内
     *
     * @param view   Component
     * @param touchX touch点的x坐标
     * @param touchY touch点的Y坐标
     * @return boolean isTouchView
     */
    private boolean isTouchView(Component view, int touchX, int touchY) {
        Rect rect = new Rect();
        view.getWindowVisibleRect(rect);
        return rect.contains(touchX, touchY, touchX + 1, touchY + 1);
    }

    public void setExpand(boolean expand) {
        mIsExpand = expand;
    }

    // 是否处于展开状态
    public boolean isExpanding() {
        return mIsExpand;
    }

    /**
     * 在滚动状态
     *
     * @param y                    相对RecyclerView的距离
     * @param deltaY               偏移量
     * @param maxParentScrollRange 最大滚动距离
     */
    public void onScroll(float y, float deltaY, int maxParentScrollRange) {
        int scrollY = getScrollValue(AXIS_Y);
        if (mScrollRange != maxParentScrollRange) {
            mScrollRange = maxParentScrollRange;
        }
        // 越界检测
        if (Math.abs(deltaY) > maxParentScrollRange) {
            if (deltaY > 0) {
                deltaY = maxParentScrollRange;
            } else {
                deltaY = -maxParentScrollRange;
            }
        }
        // 处于展开状态
        if (y <= 0) {
            scrollTo(0, (int) deltaY);
        } else if (y > 0 && scrollY != 0) { // 处于收起状态
            scrollTo(0, (int) (mScrollRange + deltaY));
        }
        setComponentPosition(getLeft(), initTop - getScrollValue(AXIS_Y), getRight(),
                initTop - getScrollValue(AXIS_Y) + getHeight());
        if (mListener != null) {
            mListener.onScroll(getScrollValue(AXIS_Y));
        }
    }

    /**
     * onFiling
     *
     * @param velocityY y方向速度
     */
    public void onFiling(int velocityY) {
        int scrollY = getScrollValue(AXIS_Y);
        // 判定非临界状态
        if (scrollY != 0 && scrollY != mScrollRange) {
            // y轴速度是否大于最小抛速度
            if (Math.abs(velocityY) > mMinFlingVelocity) {
                if (velocityY > mScrollRange || velocityY < -mScrollRange) {
                    startScroll(velocityY > mScrollRange);
                } else {
                    collapseOrExpand(scrollY);
                }
            } else {
                collapseOrExpand(scrollY);
            }
        }
    }

    /**
     * 展开或收起
     *
     * @param scrollY scrollY
     */
    private void collapseOrExpand(int scrollY) {
        // MAX_EXPAND_FACTOR = 6
        int maxExpandY = mScrollRange / MAX_EXPAND_FACTOR;
        if (isExpanding()) {
            startScroll(scrollY > maxExpandY);
        } else {
            startScroll(scrollY > (mScrollRange - maxExpandY));
        }
    }

    /**
     * 开始滚动
     *
     * @param isExpand 是否展开
     */
    private void startScroll(boolean isExpand) {
        mIsExpand = isExpand;
        animatorValue.setDuration(100);
        animatorValue.setValueUpdateListener(new AnimatorValue.ValueUpdateListener() {
            @Override
            public void onUpdate(AnimatorValue animatorValue, float v) {
                int nowScroll = getScrollValue(AXIS_Y);
                int needScroll = mScrollRange - getScrollValue(AXIS_Y);
                if (isExpand) {
                    scrollTo(0, (int) (nowScroll + v * needScroll));
                    setComponentPosition(getLeft(), -(int) (nowScroll + v * needScroll), getRight(), initHeight - (int) (nowScroll + v * needScroll));
                } else {
                    scrollTo(0, ((int) ((1 - v) * nowScroll)));
                    setComponentPosition(getLeft(), ((int) ((v - 1) * nowScroll)), getRight(), initHeight + (int) ((v - 1) * nowScroll));
                }
                if (mListener != null) {
                    mListener.onScroll(getScrollValue(AXIS_Y));
                }
            }
        });

        animatorValue.setStateChangedListener(new Animator.StateChangedListener() {
            @Override
            public void onStart(Animator animator) {

            }

            @Override
            public void onStop(Animator animator) {

            }

            @Override
            public void onCancel(Animator animator) {
                animataionEnd();
            }

            @Override
            public void onEnd(Animator animator) {
                animataionEnd();
            }

            @Override
            public void onPause(Animator animator) {

            }

            @Override
            public void onResume(Animator animator) {

            }
        });
        animatorValue.start();
        if (mListener != null) {
            mListener.isExpand(isExpand);
        }
    }


    private void animataionEnd() {
        if (mIsExpand) {
            // 必须保证滚动完成 再触发回调
            mContext.getUITaskDispatcher().delayDispatch(new Runnable() {
                @Override
                public void run() {
                    mListener.completeExpand();
                }
            }, SCROLL_DURATION);
        }
        mIsExpand = !mIsExpand;
    }

    public void computeScroll() {
        if (mOverScroller.updateScroll()) {
            setScrollbarSweepAngle(mOverScroller.getCurrValue(AXIS_Y));
            invalidate();
        }

    }

    public interface OnScrollListener {

        void onScroll(int scrollY);

        /**
         * 是否展开
         *
         * @param isExpand 是否展开
         */
        void isExpand(boolean isExpand);

        // 完全展开
        void completeExpand();
    }

    public void setOnScrollListener(OnScrollListener listener) {
        mListener = listener;
    }
}
